package com.chaudcast;

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.StreamConnection;

/**
 * A thread which downloads from a StreamConnection
 */
public class ConnectionThread extends Thread
{    	
    /* temporary storage array */
	private byte[] _data;
    /* reference to the circular buffer */
    private CircularByteBuffer _buffer;
    /* connection used for data retrieval */
    private StreamConnection _connection;
    /* connection used for data retrieval */
    private InputStream _stream;
    /* bytes read at each attempt */
    private int _readBytes;
    /* bytes read since the start of this thread */
    private int _totalBytes;
    
    private int available;

    public ConnectionThread (InputStream stream, CircularByteBuffer buffer) throws IOException {
    	_data = new byte[Network.READ_CHUNK];
    	_buffer = buffer;
    	_readBytes = 0;
    	_totalBytes = 0;
    	_stream = stream;
    	System.out.println("Created connection thread.");
    	ChaudCast.updateStatus("Streaming...");
    }
    
	/**
     * Fill the buffer
     * @see java.lang.Thread#run()
     */
    public void run()
    {
    	System.out.println("Connection thread running...");
    	while (!Network._stop) {
        	try {
        		_readBytes=_stream.read(_data);
        	} catch (IOException ioe){
        		System.out.println ("IOException when trying to read.");
        		Network.connectionDropped(ioe);
        		break;
        	} catch (NullPointerException npe) {
        		System.out.println ("Null Pointer Exception when trying to read.");
        		Network.connectionDropped(new IOException());
        		break;
        	}
    		
        	_totalBytes += _readBytes;
    		Network.addBytesRead(_readBytes);
    		
    		try {
    				_buffer.getOutputStream().write(_data);
    				available = _buffer.getAvailable();

    				// update initial buffering
				 	if (!Network.bufferingComplete() && _totalBytes > Network.getStartBuffer())
   				 	{
				 		synchronized(Network._startBufferMutex) {
				 			// We have enough of a buffer to begin playback
				 			Network.bufferingComplete(true);
				 			Network._startBufferMutex.notifyAll();
				 			ChaudCast.updateStatus("Playing...");
				 			System.out.println("Initial Buffering Complete");
				 		}
   				 	}
				 	
				 	// update paused
				 	if (!Network._paused && available < Network._pauseBytes)
   				 	{
				 		Network._paused=true;
   				 	}
				 	if (Network._paused && available > Network._resumeBytes) {
			 			// We have enough of a buffer to begin playback
				 		Network._paused=false;
				 		synchronized(Network._pauseMutex) {
				 			Network._pauseMutex.notifyAll();
				 		}
			 			ChaudCast.updateStatus("Playing...");
			 			System.out.println("Buffering Complete");
				 	}
				 	
    		} catch (IOException ioe) {
    			Network.bufferFull(ioe);
    		}
    	}
    	return;
    }
    
	/**
     * Closes the stream that belong to this thread
     */
    public void stop() throws IOException {
    	if (_stream != null && _connection != null) {
    			System.out.println("Trying to close stream...");
				_stream.close();
    	}
    	_stream = null;
    }
    
	/**
     * Returns the total bytes read by this thread
     */
    public int getTotal() {return _totalBytes;}
}